package com.it.gmall.mq.service;

import com.alibaba.fastjson.JSONObject;
import com.it.gmall.mq.entity.GmallCorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.UUID;

@Service
public class SendMsgService {

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private RedisTemplate redisTemplate;


    public void sendMsg(String exchange, String routingKey, Object msg) {

        /* GmallCorrelationData对象用来扩充CorrelationData对象的属性
        *
        * 因为重发消息需要CorrelationData这个对象(交换机、routing key、msg、发送次数)
        * 此对象用于发送失败后 将此对象返回到交换机应答队列应答
        * 目的是为了重消息
        * **/

        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        gmallCorrelationData.setExchange(exchange); // 交换机
        gmallCorrelationData.setMessage(msg); // 消息
        gmallCorrelationData.setRoutingKey(routingKey); // routing key

        /*为了在队列应答失败的时候
        重发消息的时候可以获取重发次数
        将gmallCorrelationData对象存入redis缓存中
        保证key值的唯一性 将uuid设入到gmallCorrelationData对象中

        gmallCorrelationData没有实现序列化 手动转化为json*/
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        gmallCorrelationData.setId(uuid);
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));

        // 发送消息
        rabbitTemplate.convertAndSend(exchange,routingKey,msg,gmallCorrelationData);
    }

    /*发送基于死信的延迟消息*/
    public void sendMsgDeadLetter(String exchange, String routingKey, Object msg, int ttl) {
        // 交换机和队列应答失败
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        gmallCorrelationData.setExchange(exchange); // 交换机
        gmallCorrelationData.setMessage(msg); // 消息
        gmallCorrelationData.setRoutingKey(routingKey); // routing key
        gmallCorrelationData.setDelay(true); // 是延迟消息
        gmallCorrelationData.setDelayTime(ttl); // 延迟时长 单位秒

        // 为了交换机应答失败
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        gmallCorrelationData.setId(uuid);
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));

        // 发消息
        /*String exchange, String routingKey, Object message, MessagePostProcessor messagePostProcessor,
			CorrelationData correlationData*/
        rabbitTemplate.convertAndSend(exchange,routingKey,msg,message -> {

            /*队列的ttl在配置文件中配置为10秒延迟
            * 消息的ttl延迟时间由页面传进来
            *
            * 最终接消息的延迟以哪个为准？
            * 以时间短的那个为准*/
            System.out.println("发消息时间：" + new Date());
            message.getMessageProperties().setExpiration(String.valueOf(ttl*1000)); // 设置延迟时间 单位是毫秒
            return message;
        },gmallCorrelationData);

    }

    /*发送基于插件的延迟消息*/
    public void sendMsgDelayedMsg(String exchange, String routingKey, Object msg, int delayTime) {
        // 交换机和队列应答失败
        GmallCorrelationData gmallCorrelationData = new GmallCorrelationData();
        gmallCorrelationData.setExchange(exchange); // 交换机
        gmallCorrelationData.setMessage(msg); // 消息
        gmallCorrelationData.setRoutingKey(routingKey); // routing key
        gmallCorrelationData.setDelayMsg(true); // 是否是延迟插件
        gmallCorrelationData.setDelayTimeMsg(delayTime); // 延迟时间

        // 为了交换机应答失败
        String uuid = UUID.randomUUID().toString().replaceAll("-","");
        gmallCorrelationData.setId(uuid);
        redisTemplate.opsForValue().set(uuid, JSONObject.toJSONString(gmallCorrelationData));

        // 发消息
        /*String exchange, String routingKey, Object message, MessagePostProcessor messagePostProcessor,
			CorrelationData correlationData*/
        rabbitTemplate.convertAndSend(exchange,routingKey,msg,message -> {

            /*队列的ttl在配置文件中配置为10秒延迟
             * 消息的ttl延迟时间由页面传进来
             *
             * 最终接消息的延迟以哪个为准？
             * 以时间短的那个为准*/
            System.out.println("发消息时间：" + new Date());
            message.getMessageProperties().setDelay(delayTime*1000); // 设置延迟时间 单位是毫秒
            return message;
        },gmallCorrelationData);
    }
}
